<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        body {
            background-color: #000;
        }
        #wrap {
            width: 700px;
            height: 500px;
            margin: 50px auto;
        }
        #box {
            position: relative;
            width: 100%;
            height: 100%;
            overflow: hidden;
            
        }
        .bg0 {
            background: url(./img/bg0.jpg) no-repeat center/cover;
        }
        .bg1 {
            background: url(./img/bg1.jpg) no-repeat center/cover;
        }
        .bg2 {
            background: url(./img/bg2.jpg) no-repeat center/cover;
        }
        .bg3 {
            background: url(./img/bg3.jpg) no-repeat center/cover;
        }
        .bg4 {
            background: url(./img/bg4.jpg) no-repeat center/cover;
        }
        h1 {
            color: darkgray;
            text-align: center;
            padding: 30px;
        }
        div.init {
            background-color: #fff;
            width: 200px;
            height: 50px;
            line-height: 50px;
            text-align: center;
            margin: 40px auto;
            font-size: 20px;
            font-weight: 800;
            color: rgb(32, 19, 2);
            cursor: pointer;
            border-radius: 10px;
            background-color: rgb(252, 215, 137);
        }
        div.footer {
            position: absolute;
            bottom: 5px;
            right: 10px;
            color: rgb(94, 18, 165);
        }
        
        img:not(.boom) {
            width: 100%;
            height: 100%;
        }
        .enemy.small {
            position: absolute;
            width: 40px;
            /* height: 30px; */
        }

        .enemy.small .blood {
            position: absolute;
            top: -7px;
            width: 100%;
            height: 5px;
            border: 1px solid red;
            box-sizing: border-box;
        }
        .enemy.small .blood p {
            height: 100%;
            background-color: red;
        }
        /* 大的敌军飞机 */
        .enemy.big {
            position: absolute;
            width: 50px;
            /* height: 40px; */
        }

        .enemy.big .blood {
            position: absolute;
            top: -7px;
            width: 100%;
            height: 5px;
            border: 1px solid red;
            box-sizing: border-box;
        }
        .enemy.big .blood p {
            height: 100%;
            background-color: red;
        }
        .plane {
            position: absolute;
        }
        .plane.big {
            position: absolute;
            width: 60px;
        }
        .plane.small {
            position: absolute;
            width: 80px;
        }
        /* 子弹 */
        .biu {
            position: absolute;
        }
        .biu.strong1 {
            width: 16px;
            height: 16px;
        }
        .biu.strong2 {
            width: 20px;
            height: 20px;
        }
        /* 爆炸图片及其动画 */
        img.boom {
            position: absolute;
            animation: opa 1s;
        }
        @keyframes opa {
            0% {
                opacity: 1;
            }
            25% {
                opacity: 0.5;
            }
            50% {
                opacity: 1;
            }
            100% {
                opacity: 0;
            }
        }
        /* 奖品 */
        .prize {
            position: absolute;
            width: 50px;
            height: 50px;
            font-size: 50px;
            text-align: center;
            line-height: 50px;
            border: 1px dashed red;
            color: red;
            font-weight: bold;
            box-sizing: border-box;
            animation: prize 1s infinite;
        }
        @keyframes prize {
            0% {
                transform: scale(1);
            }
            50% {
                transform: scale(1.2);
            }
            100% {
                transform: scale(1);
            }
        }
        /* 统计得分 */
        .score {
            position: absolute;
            top: 0;
            left: 0;
            width: 70px;
            height: 30px;
            color: #fff;
            font-size: 20px;
        }
        .record {
            width: 200px;
            height: 80px;
            border: 1px double rgb(255, 255, 255);
            background-color: black;
            padding: 10px;
            margin: 100px auto;
            color: white;
            box-sizing: border-box;
        }
        .record p {
            text-align: center;
            font-size: 25px;
            font-weight: 700;
            padding: 10px;
            color: yellowgreen;
        }
        .btn {
            width: 100px;
            height: 30px;
            background-color: rgb(241, 238, 30);
            color: rgb(235, 23, 23);
            font-weight:700;
            border-radius: 10px;
            text-align: center;
            line-height: 30px;
            margin: 20px auto;
        }

    </style>
</head>
<body>
    <div id="wrap">
        <div id="box" class="bg0">
            <!-- 生成小的敌军飞机 -->
            <!-- <div class="enemy_small">
                <div class="blood"><p></p></div>
                <img src="img/enemy_small.png" width="108" height="80" alt="">
            </div> -->
            <!-- 生成大的敌军飞机 -->
            <!-- <div class="enemy_big">
                    <div class="blood"><p></p></div>
                    <img src="img/enemy_big.png" width="260" height="200" alt="">
                </div> -->
            <!-- <h1>飞机大战</h1>
            <div class="init">简单模式</div>
            <div class="init">一般模式</div>
            <div class="init">困难模式</div>
            <div class="init">地狱模式</div> -->
            <!-- <div class="plane big">
                    <img src="img/plane_1.png" alt="">
                </div> -->
            <!-- 爆炸 -->
            <!-- <img src="./img/boom_small.png" class="boom" alt=""> -->
            <!-- <div class="prize">乖</div> -->
            <!-- 统计分数 -->
            <!-- <div class="record">最终得分 : <p>1000</p></div>
            <div class="btn">再来一次</div>
            <audio src="img/game_music.mp3" autoplay></audio> -->
        </div>
    </div>

    <script>
        (function(){
            let box = document.getElementById("box"),
                timer = null,
                boxWidth = box.clientWidth,
                boxHeight = box.clientHeight,
                option = ["简单模式","一般模式","困难模式","地狱模式"],
                enemyspeed = [400,350,300,200],
                //全局选中所有敌军飞机
                enePlane = document.getElementsByClassName("enemy");
                plane = document.getElementsByClassName("plane");
                prize = document.getElementsByClassName("prize");
                // 提前存储敌军飞机的信息,包括大飞机和小飞机
                defaultEne = {
                    big:{
                        width: 260,
                        height: 200,
                        strong: 5 //血条值
                    },
                    small:{
                        width: 108,
                        height: 80,
                        strong: 1
                    }
                },
            
                defaultPlane = {
                    big: {
                        width: 97,
                        height: 97,
                        src: "img/plane_1.png"
                    },
                    small: {
                        width: 122,
                        height: 95,
                        src: "img/plane_0.png"
                    }
                };
            //初始页面生成
            init();
            function init(){
                let h1 = document.createElement("h1");
                h1.innerHTML = "飞机大战";
                box.appendChild(h1);
                for(let i = 0; i < option.length; i++){
                    let div = document.createElement("div");
                    div.className = "init";
                    div.innerHTML = option[i];
                    div.onclick = function(e){
                        //生成飞机函数,通过传参(哪种模式)调用
                        start(i,e);
                    };
                    box.appendChild(div);
                }
                let footer = document.createElement("div");
                footer.innerHTML = "Made by Lisa";
                footer.className = "footer";
                box.appendChild(footer);
            }

            //生成飞机敌军(调用enemy())和我军(调用airPlane()),输入参数为模式,不同模式,生成的飞机种类速度不同
            function start(idx,e){
                box.innerHTML = "";
                box.className = "bg"+(idx+1);
                let model = ["small","big","small","small"];
                //生成敌军飞机
                box.eneTime = setInterval(()=>{
                    enemy(idx,model[random(0,3)]);
                },enemyspeed[idx]);
                airPlane(idx,e,"small");
                //开始奖品的功能生成
                box.prizeTimer = setInterval(() => {
                    createPrize(["力","速"][random(0,1)]);
                }, 3000);
                //统计分数
                showScore();
                //添加背景音乐 <audio src="img/game_music.mp3" autoplay></audio>
                addAudio("img/game_music.mp3");

            }

            //生成敌军
            function enemy(idx,model){
                //通过定时器控制生成敌军,敌军飞机从页面顶端随机出现(定位left值),出现后向下移动(定位top值),且不同模式下,敌军飞机的生成速度不同.每个敌军飞机速度不同,即步长不同.
                //生成敌军飞机时,定时器间隔时间越短,生成的敌军飞机越多. 
                    let ene = document.createElement("div");
                    ene.className = "enemy " + model;
                    let blood = document.createElement("div");
                    blood.className = "blood";
                    let p = document.createElement("p");
                    let img = document.createElement("img");
                    img.src = "img/enemy_"+ model +".png";
                    img.width = defaultEne[model].width;
                    img.height = defaultEne[model].height;
                    //预存敌人的身份,以便于跟子弹威力计算,大的敌军飞机,需要更多地子弹攻击才能击落
                    ene.model = model;
                    //定义自身宽度属性,防止没加载时布局变形时,图片可以定义的大小显示
                    ene.style.top = 0;
                    ene.style.left = random(0,boxWidth-img.width)+"px";
                    //敌军飞机的血条值,威力
                    ene.strong = defaultEne[model].strong;
                    //飞机出厂时速度,即每个飞机出厂时自带一个移动步长,步长不同,每个飞机移动的速度不同,如速度随机在3~6之间
                    ene.speed = random(3,6);
                    box.appendChild(ene).appendChild(blood).appendChild(p);
                    ene.appendChild(img);
                    //让飞机向下移动,通过改变top值下移,且当飞机移动到盒子低端时就移除该飞机
                    eneloading();
                    function eneloading(){
                        ene.style.top = ene.offsetTop + ene.speed+"px";
                        if(ene.offsetTop >= boxHeight-ene.offsetHeight){
                            //敌军飞机下移到底部,中途未与我军飞机碰撞.
                            box.removeChild(ene);
                        }else{
                            //没有达到底部,需要检测是否与我军发生碰撞,让敌军飞机不断下移,
                            if(plane[0] && isCollide(plane[0],ene)){
                                boom(ene);
                                //游戏结束gameOver()
                                //1.我军要爆炸
                                //2.画面要静止
                                gameOver();
                            }else{
                                plane[0] && requestAnimationFrame(eneloading);
                            }
                            
                        }
                    }

            }

            //生成我军,鼠标位置决定飞机位置
            function airPlane(idx,e,model){
                let maxTop,minTop,maxLeft,minLeft;
                //生成我军飞机,并确定我军飞机的初始位置
                let plane = document.createElement("div");
                let img = document.createElement("img");
                img.src = defaultPlane[model].src;
                img.width = defaultPlane[model].width;
                img.height = defaultPlane[model].height;
                plane.className = "plane " + model;
                // let sY = e.clientY;
                // let sX = e.clientX;
                //定义初始子弹威力及条数
                plane.strong = 0;
                plane.count = 0;
                plane.model = model;
                box.appendChild(plane).appendChild(img);
                //飞机图片信息加载,加载后再生成子弹的威力
                img.onload = function(){
                    plane.style.top = e.clientY - box.offsetTop + plane.clientHeight/2 + "px";
                    plane.style.left = e.clientX- box.offsetLeft + plane.clientWidth/2+"px";
                    //限制我军移动范围
                    minTop = 0;
                    maxTop = box.clientHeight - plane.clientHeight;
                    minLeft = 0;
                    maxLeft = box.clientWidth - plane.clientWidth;
                }
                //拖拽
                document.onmousemove = function(e){
                    let top = e.clientY - box.offsetTop - plane.clientHeight/2,
                        left = e.clientX- box.offsetLeft + plane.clientWidth/2;
                    top = Math.max(minTop,top);//通过最大值限定最小值
                    top = Math.min(maxTop,top);//通过最小值限定最大值
                    left = Math.max(minLeft,left);
                    left = Math.min(maxLeft,left);
                    plane.style.top = top + "px";
                    plane.style.left = left + "px";

                    //我军飞机每次移动时,检测是否跟prize发生碰撞,碰撞就获得奖励
                    for(let i = 0; i < prize.length ; i++){
                        if(isCollide(plane,prize[i])){

                            if(prize[i].attr === "速"){
                                plane.strong++;//子弹威力加一,打掉敌军血条值能力加一
                            }else if (prize[i].attr === "力"){
                                plane.count++;//我军飞机子弹条数加一
                                //一次吃奖品数量不能超过2个
                                if(plane.count > 2){
                                    alert("知足者常乐");
                                    gameOver();
                                }
                            }
                            //获得奖品后,移除奖品
                            clearTimeout(prize[i].timer);
                            box.removeChild(prize[i]);
                        }
                    }
                }
                //生成子弹
                let speed = [300,250,200,150][idx];//子弹的生成速度
                    bulletSpeed = [4,5,6,7][idx];//子弹的移动速度
                    //添加音乐
                    audio = document.createElement("audio");
                    audio.autoplay = true;//true为自动播放
                    audio.loop = true;//循环播放
                    box.appendChild(audio);

                //子弹发射
                plane.timer = setInterval(function(){
                    for(let i = 0; i<= plane.count; i++){
                        bulletCreate({
                            strong: plane.strong,
                            count: plane.count,
                            i: i //用来确定子弹条数和left位置
                        });
                        //添加音乐的路径
                        audio.src = plane.count > 0? "img/enemy2_out.mp3" : "img/bullet.mp3";
                    }
                    
                },speed);
                function bulletCreate(obj){
                    let bullet = document.createElement("img");
                    bullet.src = "img/fire.png";
                    bullet.className = "biu strong1";
                    //子弹的威力,即能打掉敌人的血条值取决于奖品,初始威力为1
                    bullet.strong = 1 + plane.strong;
                    //子弹的条数,初始为1条
                    bullet.count = 1 + plane.count;
                    box.appendChild(bullet);
                    //子弹的top值在飞机当前位置
                    bullet.style.top = plane.offsetTop + "px";
                    
                    
                    //判断子弹条数
                    if(obj.count === 0){
                        //只有一条子弹时,在中间
                        //子弹的left位置在飞机当前定位基础上右移飞机一半再左移子弹一半
                        bullet.style.left = plane.offsetLeft + plane.offsetWidth/2 - bullet.offsetWidth/2 + "px";
                    }else if(obj.count === 1){
                        //两条子弹,在左边和右边  bullet.style.left = ["左边","右边"][obj.i] + "px";
                        bullet.style.left = [plane.offsetLeft, plane.offsetLeft + plane.offsetWidth - bullet.offsetWidth][obj.i] + "px";
                    }else if(obj.count === 2){
                        bullet.style.left = [plane.offsetLeft, plane.offsetLeft + plane.offsetWidth/2 - bullet.offsetWidth/2, plane.offsetLeft + plane.offsetWidth - bullet.offsetWidth][obj.i] + "px";
                    }

                    //让子弹移动
                    bulletLaunch();

                    function bulletLaunch(){
                        bullet.style.top = bullet.offsetTop - bulletSpeed + "px";
                        if(bullet.offsetTop <= 0){
                            //如果子弹的定位到盒子外面了,就移除子弹
                            box.removeChild(bullet);
                        }else{
                            //如果子弹定位还在盒子里,就继续让这颗子弹不停的上移,前提是我军飞机还存在
                            plane.parentNode && (bullet.timer = requestAnimationFrame(bulletLaunch));
                            //检测子弹和敌军碰撞情况
                            for(let i = 0; i < enePlane.length; i++){
                                //被父元素使用removeChild删除的节点,只是不存在于该页面中,但仍存在于js中
                                //先判断敌军飞机是否在页面中,在页面中才有可能发生碰撞
                                if(enePlane[i] && isCollide(bullet,enePlane[i])){
                                    //发生碰撞后,移除子弹清除子弹移动的定时器,并将敌军血条值减1
                                    //清除子弹移动定时器
                                    cancelAnimationFrame(bullet.timer);
                                    //移除子弹
                                    box.removeChild(bullet);
                                    //敌军血条值按照子弹威力减少
                                    enePlane[i].strong -= bullet.strong;
                                    //动态修改被击中敌军飞机的血条值样式,如果打完了就生成爆炸图片
                                    //首先要获取敌军飞机的血条即.enemy .blood p
                                    enePlane[i].children[0].children[0].style.width = enePlane[i].strong/defaultEne[enePlane[i].model].strong * enePlane[i].children[0].clientWidth + "px";
                                    
                                    //让敌军爆炸
                                    if(enePlane[i].strong <= 0){
                                        //统计计分情况 击落小的敌军飞机得1分,击落大的敌军飞机得5分
                                        if(enePlane[i].model === "small"){
                                            box.score ++;
                                        }else if(enePlane[i].model === "big"){
                                            box.score += 5;
                                        }
                                        boom(enePlane[i]);
                                        document.getElementsByClassName("score")[0].innerHTML = box.score;
                                        
                                        

                                    }
                                    
                                }
                            }
                        }
                    }
                }

            }
            //爆炸
            function boom(obj){
                //爆炸的图片替换爆炸的敌军飞机图片--与敌军飞机定位一致
                let img = document.createElement("img");
                img.src = "img/boom_" + obj.model + ".png";
                img.width = obj.clientWidth;
                img.height = obj.clientHeight;
                img.className = "boom";
                img.style.top = obj.offsetTop + "px";
                img.style.left = obj.offsetLeft + "px";
                //移除obj图片,替换为爆炸图片
                box.removeChild(obj);
                box.appendChild(img);
                //爆炸图片消失,当动画样式结束时将爆炸图片移除,使用事件监听
                img.addEventListener("webkitAnimationEnd",function () {
                                    //注意驼峰式书写webkitAnimationEnd
                    box.removeChild(this);
                });
                let audio = document.createElement("audio");
                //判断是否是敌军飞机爆炸,如果是敌军飞机爆炸就播放爆炸声,否则我军飞机爆炸播放游戏结束的声音
                audio.src = obj.className === "enemy"? "img/game_music.mp3" : "img/game_over.mp3";
                audio.autoplay = true;//true为自动播放
                audio.loop = false;//循环播放
                audio.volume = 0.5; //音量大小在0~1之间
                
                //为了提高效率,每次播放玩音乐就将该标签删除掉
                audio.addEventListener("ended",function(){
                    box.removeChild(this);
                })
                box.appendChild(audio);
            }
            //是否发生碰撞,子弹与敌军
            function isCollide (obj1,obj2){
                //获取子弹和敌军飞机四条边的位置
                let top1 = obj1.offsetTop,
                    left1 = obj1.offsetLeft,
                    right1 = left1 + obj1.offsetWidth,
                    bottom1 = top1 + obj1.offsetHeight,
                    top2 = obj2.offsetTop,
                    left2 = obj2.offsetLeft,
                    right2 = left2 + obj2.offsetWidth,
                    bottom2 = top2 + obj2.offsetHeight;
                
                return !(top1 > bottom2 || left1 > right2 || bottom1 < top2 || right1 < left2);
            }
            function random(a,b){
                return Math.floor(Math.random()*(b-a+1)+a);
            }
            //游戏结束,画面静止
            function gameOver(){
                //注销我军移动事件
                document.onmousemove = null;
                //关闭生成敌军的定时器
                clearInterval(box.eneTime);
                //关闭生成子弹的定时器
                clearInterval(plane[0].timer);
                //清除生成奖品的定时器
                clearInterval(box.prizeTimer);
                //我军的爆炸效果和删除我军
                boom(plane[0]);
                //统计计分情况
                setTimeout(getScore,1000);
            }

            //奖品函数 --- 速-威力,力-子弹条数
            function createPrize(inner){
                let div = document.createElement("div");
                div.innerHTML = inner;
                div.className = "prize";
                div.attr = inner;
                div.style.top = random(0,boxHeight-50) + "px";
                div.style.left = random(0,boxWidth-50) + "px";
                box.appendChild(div);
                //奖品不能一直待在盒子里,几秒之后消失
                div.timer = setTimeout(() => {
                    box.removeChild(div);
                }, 3000);
            }
            //计分功能 getScore()
            function getScore(){
                //游戏结束先清除屏幕
                //<div class="record">最终得分 : <p>1000</p></div>
                //<div class="btn">再来一次</div>
                box.innerHTML = "";
                let div1 = document.createElement("div");
                    div2 = document.createElement("div");
                    div1.className = "record";
                    //box.score在敌军爆炸时记录
                    div1.innerHTML = "最终分数:<p>" + box.score + "</p>";
                    div2.className = "btn";
                    div2.innerHTML = "再来一次";
                    div2.onclick = function(){
                        box.innerHTML = "";
                        init();
                    }
                    box.appendChild(div1);
                    box.appendChild(div2);
            }
            //showScore()从start就开始计分
            function showScore(){
                let span = document.createElement("span");
                span.innerHTML = box.score = 0;
                span.className = "score";
                box.appendChild(span);
            }
            function addAudio(src){
                let audio = document.createElement("audio");
                audio.src = src;
                audio.autoplay = true;//true为自动播放
                audio.loop = true;//循环播放
                audio.volume = 0.4; //音量大小在0~1之间
                box.appendChild(audio);
            }

        })();
    </script>
</body>
</html>